package org.mayuanxiaonong.timserver.codec.msgpack;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import java.util.List;

import org.mayuanxiaonong.timserver.codec.PacketEncoder;
import org.mayuanxiaonong.timserver.pack.config.MessagePackConfig;
import org.mayuanxiaonong.timserver.pack.msgpack.IPack;
import org.mayuanxiaonong.timserver.packet.Packet;
import org.mayuanxiaonong.timserver.packet.SimplePacket;
import org.msgpack.MessagePack;

import static org.mayuanxiaonong.timserver.pack.msgpack.IPack.*;
import static io.netty.buffer.Unpooled.*;

/**
 * MessagePack报文体解码处理器
 * 
 * <pre>
 * 1、将{@link ByteBuf}解码为{@link IPack}
 * 
 * 2、将{@link IPack}构建为{@link Packet}
 * 
 * @author 9527
 *
 */
public class MessagePackEncoder extends PacketEncoder {

	@Override
	protected void encode(ChannelHandlerContext ctx, Packet msg,
			List<Object> out) throws Exception {
		super.encode(ctx, msg, out);

		byte[] bytes = null;
		if (msg instanceof SimplePacket) {
			bytes = buildPack(msg.getType());
		} else {
			int type = msg.getType();
			IPack iPack = MessagePackConfig.getInstance().getPack(type);
			if (iPack == null) {
				// 不支持的协议
			} else {
				IPack pack = iPack.fromPacket(msg);
				byte[] packBytes = new MessagePack().write(pack);
				bytes = this.buildPack(type, pack.getVersion(), packBytes);
			}
		}

		if (bytes != null) {
			out.add(wrappedBuffer(bytes));
		}
	}

	/**
	 * 构建只有业务类型的报文
	 * 
	 * @param type
	 * @return
	 */
	private byte[] buildPack(int type) {
		int length = HEAD_SIMPLE_TYPE_LEN;
		byte[] pack = new byte[length];
		int pos = 0;
//		// 构建报文头-长度
//		for (int i = 1; i <= HEAD_LENGTH_LEN; i++) {
//			pack[pos++] = (byte) ((length >> ((HEAD_LENGTH_LEN - i) * 8)) & 0xff);
//		}
		// 构建报文头-业务类型
		for (int i = 1; i <= HEAD_SIMPLE_TYPE_LEN; i++) {
			pack[pos++] = (byte) ((type >> ((IPack.HEAD_SIMPLE_TYPE_LEN - i) * 8)) & 0xff);
		}

		return pack;
	}

	/**
	 * 构建有报文体的报文
	 * 
	 * @param type
	 * @param version
	 * @param body
	 * @return
	 */
	private byte[] buildPack(int type, int version, byte[] body) {
		int length = IPack.HEAD_TYPE_LEN + IPack.HEAD_VERSION_LEN + body.length;
		byte[] pack = new byte[length];
		int pos = 0;
//		// 构建报文头-长度
//		for (int i = 1; i <= IPack.HEAD_LENGTH_LEN; i++) {
//			pack[pos++] = (byte) ((length >> ((IPack.HEAD_LENGTH_LEN - i) * 8)) & 0xff);
//		}
		// 构建报文头-业务类型
		for (int i = 1; i <= IPack.HEAD_TYPE_LEN; i++) {
			pack[pos++] = (byte) ((type >> ((IPack.HEAD_TYPE_LEN - i) * 8)) & 0xff);
		}
		// 构建报文头-版本号
		for (int i = 1; i <= IPack.HEAD_VERSION_LEN; i++) {
			pack[pos++] = (byte) ((version >> ((IPack.HEAD_VERSION_LEN - i) * 8)) & 0xff);
		}
		// 构建报文体
		System.arraycopy(body, 0, pack, pos, body.length);
		pos += body.length;

		return pack;
	}

}
